local Class = require('lua.lang.Class')
local Varargs = require('lua.vm.Varargs')
local PairVarargs = require('lua.vm.PairVarargs')
local ArrayPartVarargs = require('lua.vm.ArrayPartVarargs')

--- @class ArrayVarargs : Varargs
--- @field v LuaValue[]
--- @field r Varargs
local ArrayVarargs = Class {
	__extends = Varargs
}

--- @param v LuaValue[]
--- @param r Varargs
--- @return PairVarargs
function ArrayVarargs:new(v, r)
	--- @type ArrayVarargs
	local o = {}
	o.v = v
	o.r = r
	return setmetatable(o, ArrayVarargs)
end

--- @param i number
--- @return LuaValue
function ArrayVarargs:arg(i)
	if i < 1 then
		return require('lua.vm.LuaNil')._NIL
	elseif i <= #self.v then
		return self.v[i]
	else
		return self.r:arg(i - #self.v)
	end
end

--- @return number
function ArrayVarargs:narg()
	return #self.v + self.r:narg()
end

--- @return LuaValue
function ArrayVarargs:arg1()
	return #self.v > 0 and self.v[1] or self.r:arg1()
end

--- @param start number
--- @return Varargs
function ArrayVarargs:subArgs(start)
	if start <= 0 then
		self:argError(1, 'start must be > 0')
	elseif start == 1 then
		return self
	elseif start > #self.v then
		return self.r:subArgs(start - #self.v)
	end
	local offset = start - 1
	local length = #self.v - offset
	if length == 0 then
		return self.r
	elseif length == 1 then
		return self.r:narg() > 0 and PairVarargs:new(self.v[offset + 1], self.r) or self.v[offset + 1]
	elseif length == 2 then
		return self.r:narg() > 0 and ArrayPartVarargs:new(self.v, offset, length, self.r) or
				PairVarargs:new(self.v[offset + 1], self.v[offset + 2])
	else
		return ArrayPartVarargs:new(self.v, offset, length , self.r)
	end
end

return ArrayVarargs